﻿using System;
using System.ServiceModel;
using System.Diagnostics;

namespace MultiViewer.Network
{
    public class ServerNodeProxy : DuplexClientBase<IServerNode>
    {
        public ServerNodeProxy(ClientNode node) : base(new InstanceContext(node),"mvClientEndPoint")
        {
        }

        public int Connect(int nodeId)
        {
            return Channel.Connect(nodeId);
        }

        public void Disconnect(int nodeId)
        {
            Channel.Disconnect(nodeId);
        }

        public void Perform(Message request)
        {
             Channel.Perform(request);
        }
    }

    public class ClientNode : Node,IClientNode
    {
        /// <summary>Proxy object to connect to server</summary>
        private ServerNodeProxy proxy;

        public ClientNode(params string[] args)
        {
            string ids = GetParameter("multiViewerNodeID", "mvid", args);
            if (!Int32.TryParse(ids, out nodeId))
                throw new Exception("Node id is not specified neither in config nor in command line args");
            if (nodeId < 1)
                throw new Exception("Node id must be positive");
            proxy = new ServerNodeProxy(this);
            nodeCount = proxy.Connect(nodeId);
            inited = true;
        }

        public override void Stop()
        {
            if (inited)
            {
                try
                {
                    proxy.Disconnect(nodeId);
                }
                catch (Exception exc)
                {
                    Trace.WriteLine("Failed to send Disconnect message to server: {0}", exc.Message);
                }
            }
            base.Stop();
        }

        public override int[] ConnectedNodes
        {
            get { throw new NotImplementedException(); }
        }

        public void Shutdown()
        {
        }

        public override Response[] Send(int[] nodes, Message request)
        {
            throw new NotImplementedException();
        }

        public override void Notify(int[] nodes, Message request)
        {
            throw new NotImplementedException();
        }

        /// <summary>Initiates transaction</summary>
        /// <param name="request">Transaction request</param>
        public override void Perform(Message request)
        {
            // Ask server to perform transaction
            proxy.Perform(request);
            // TODO: It should be slightly more efficient to start transaction
            // on this node here and ask server to start transactions on all
            // nodes except this one. But it is more complicated.
        }

        #region IClientNode Members

        public void OnNotification(Message message)
        {
            HandleNotification(message);
        }

        public object OnMessage(Message message)
        {
            return HandleMessage(message);
        }

        public bool OnPrepare(string id, Message message)
        {
            return HandlePrepare(id, message);
        }

        public void OnCommit(string id)
        {
            HandleCommit(id);
        }

        public void OnRollback(string id)
        {
            HandleRollback(id);
        }


        #endregion
   }
}